package cn.renhui.hermesbus.core;

import android.content.Context;

import com.google.gson.Gson;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import cn.renhui.hermesbus.ClassId;
import cn.renhui.hermesbus.utils.LogUtils;
import cn.renhui.hermesbus.Request;
import cn.renhui.hermesbus.Response;
import cn.renhui.hermesbus.utils.ServiceConnectManager;
import cn.renhui.hermesbus.utils.TypeUtils;
import cn.renhui.hermesbus.bean.RequestBean;
import cn.renhui.hermesbus.bean.RequestParameter;

public class Hermes {

    public static final int TYPE_NEW = 0;  /// 得到对象

    public static final int TYPE_GET = 1;  /// 得到单例

    private static final Hermes instance = new Hermes();  // 饿汉单例

    private Context context;
    private TypeCenter typeCenter;
    private ServiceConnectManager serviceConnectManager;

    private static final Gson GSON = new Gson();

    private Hermes() {
        typeCenter = TypeCenter.getInstance();
        serviceConnectManager = ServiceConnectManager.getInstance();
    }

    public static Hermes getDefault() {
        return instance;
    }

    public void init(Context context) {
        this.context = context.getApplicationContext();
    }

    //--------------------------------- 服务端 ----------------------------------------------

    public void register(Class<?> clazz) {
        typeCenter.register(clazz);
    }

    //--------------------------------- 客户端 ----------------------------------------------

    public void connectApp(Context context, Class<? extends HermesService> service) {
        connectApp(context, null, service);
    }

    private void connectApp(Context context, String packageName, Class<? extends HermesService> service) {
        init(context);
        serviceConnectManager.bind(context.getApplicationContext(), packageName, service);
    }

    // 获取另一个进程的对象
    public <T> T getInstance(Class<T> clazz, Object... parameters) {
        Response response = sendRequest(HermesService.class, clazz, null, parameters);
        return getProxy(HermesService.class, clazz);
    }

    private <T> T getProxy(Class<HermesService> hermesServiceClass, Class<T> tClass) {
        ClassLoader classLoader = hermesServiceClass.getClassLoader();
        T proxy = (T) Proxy.newProxyInstance(classLoader, new Class<?>[]{tClass}, new HermesInvocationHander(hermesServiceClass, tClass));
        return proxy;
    }


    private <T> Response sendRequest(Class<HermesService> hermesServiceClass, Class<T> clazz, Method method, Object[] parameters) {

        RequestBean requestBean = new RequestBean();

        String className = null;
        if (clazz.getAnnotation(ClassId.class) == null) {   //有注解
            requestBean.setClassName(clazz.getName());
            requestBean.setResultClassName(clazz.getName());
        } else { //木有注解时返回类型的全类名
            requestBean.setClassName(clazz.getAnnotation(ClassId.class).value());
            requestBean.setResultClassName(clazz.getAnnotation(ClassId.class).value());
        }
        if (method != null) {  //方法名 统一传 方法名+参数名  getInstance(java.lang.String)
            requestBean.setMethodName(TypeUtils.getMethodId(method));
        }

        RequestParameter[] requestParameters = null;
        if (parameters != null && parameters.length > 0) {
            requestParameters = new RequestParameter[parameters.length];
            for (int i = 0; i < parameters.length; i++) {
                Object parameter = parameters[i];
                String parameterClassName = parameter.getClass().getName();
                String parameterValue = GSON.toJson(parameter);

                RequestParameter requestParameter = new RequestParameter(parameterClassName, parameterValue);
                requestParameters[i] = requestParameter;
            }
        }

        if (requestParameters != null) {
            requestBean.setRequestParameters(requestParameters);
        }


        Request request = new Request(GSON.toJson(requestBean), TYPE_GET);
        LogUtils.e("Call 104");
        return serviceConnectManager.request(hermesServiceClass, request);
    }

    public <T> Response sendObjectRequest(Class hermeService, Class<T> aClass, Method method, Object[] args) {

        LogUtils.e("sendObjectRequest hermeServiceName = " + hermeService);

        RequestBean requestBean = new RequestBean();

        //set全类名
        String className = null;
        if (aClass.getAnnotation(ClassId.class) == null) {
            requestBean.setClassName(aClass.getName());
            requestBean.setResultClassName(aClass.getName());
        } else {
            requestBean.setClassName(aClass.getAnnotation(ClassId.class).value());
            requestBean.setResultClassName(aClass.getAnnotation(ClassId.class).value());
        }

        //set方法
        if (method != null) {
            requestBean.setMethodName(TypeUtils.getMethodId(method));
        }

        //set参数
        RequestParameter[] requestParameters = null;
        if (args != null && args.length > 0) {
            requestParameters = new RequestParameter[args.length];
            for (int i = 0; i < args.length; i++) {
                Object parameter = args[i];
                String parameterClassName = parameter.getClass().getName();
                String parameterValue = GSON.toJson(parameter);

                RequestParameter requestParameter = new RequestParameter(parameterClassName, parameterValue);
                requestParameters[i] = requestParameter;
            }
        }

        if (requestParameters != null) {
            requestBean.setRequestParameters(requestParameters);
        }

        Request request = new Request(GSON.toJson(requestBean), TYPE_NEW);
        LogUtils.e("Call 146");
        return serviceConnectManager.request(hermeService, request);
    }
}
